Activity启动流程(Launcher篇)

综述

ActivityManagerService 即活动管理服务,它负责管理我们应用的activity,service等与系统交互的组件,为了方便起见,我们简称为AMS。我们知道Activity在启动过程中会经历一系列的生命周期,这些生命周期反应了AMS创建和管理Activity的整个过程,并且在这之间又同时需要和WindowManagerService进行交互操作,这就导致activity的启动是个异常复杂的工作。本篇不打算对整个流程的细节做过多的分析,只涉及activity启动过程的关键部分。

Activity启动方式-Launcher

首先activity的启动方式有多种可能的情况,比如最典型的就是点击Launcher上的图标启动,或者在应用内部打开activity进行跳转,还有通过adb 来启动activity,但无论是哪种启动方式,最基本的流程都是类似的。这里我们以Launcher启动作为描述的标准场景来简单了解下在activity启动过程中都会发生什么事情以使activity能够展现在我们眼前。

Launcher是一个标准的系统桌面应用,它用来管理系统中的所有已安装的app,这些app都是以网格化的形式在Launcher中显示的。我们点击一个app图标就会开始启动整个app并启动它的主activity。

Launcher启动是会给Intent添加flag Intent.FLAG_ACTIVITY_NEW_TASK,这表示我们会为这个应用创建一个新的任务栈。紧接就是启动指定的activity,正式开始startActivity的启动。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
packages/apps/Launcher2/src/com/android/launcher2/Launcher.java

boolean startActivity(View v, Intent intent, Object tag) {
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
// Only launch using the new animation if the shortcut has not opted out (this is a
// private contract between launcher and may be ignored in the future).
boolean useLaunchAnimation = (v != null) &&
!intent.hasExtra(INTENT_EXTRA_IGNORE_LAUNCH_ANIMATION);
if (useLaunchAnimation) {
ActivityOptions opts = ActivityOptions.makeScaleUpAnimation(v, 0, 0,
v.getMeasuredWidth(), v.getMeasuredHeight());
startActivity(intent, opts.toBundle());
} else {
startActivity(intent);//调用activity的startActivity启动
}
return true;
} catch (SecurityException e) {}
return false;
}

从Launcher启动的activity默认添加了FLAG_ACTIVITY_NEW_TASK,表示为应用创建新的任务栈。

这里我们从Launcher启动传递给startActivityForResult的requestCode为-1,说明我们不接受activity的返回值。

1
2
3
4
5
6
7
8
9
10
11
Activity:   startActivity->startActivityForResult

1. [Activity.startActivityForResult]===>[Instrumention.execStartActivity]

public void startActivityForResult(Intent intent, int requestCode, Bundle options) {
……
Instrumentation.ActivityResult ar =
mInstrumentation.execStartActivity(
this, mMainThread.getApplicationThread(), mToken, this,intent, requestCode, options);
……
}

execStartActivity 参数说明,对于Launcher启动:

  • who: 为Launcher应用
  • mMainThread.getApplicationThread(): 为Launcher的ApplicationThread它是一个Binder
  • target: 为this 代表Launcher这个Activity
  • requestCode: -1
  • intent: 为要启动应用的Activity的意图
  • options: null

这里通过Instrumention来调用execStartActivity

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
2.[Instrumention.execStartActivity]===>[AMS.startActivity]
public ActivityResult execStartActivity(
Context who, IBinder contextThread, IBinder token, Activity target,
Intent intent, int requestCode, Bundle options) {
IApplicationThread whoThread = (IApplicationThread) contextThread;
……
try {
intent.migrateExtraStreamToClipData();
intent.prepareToLeaveProcess();
//通过AMS启动Activity 这个是通过binder调用完成
int result = ActivityManagerNative.getDefault()
.startActivity(whoThread, who.getBasePackageName(), intent,
intent.resolveTypeIfNeeded(who.getContentResolver()),
token, target != null ? target.mEmbeddedID : null,
requestCode, 0, null, null, options);
//检查启动的结果 这里如果Activity在manifest中未注册就会报错
checkStartActivityResult(result, intent);
} catch (RemoteException e) {}
……
return null;
}

在Instrumention中会通过ActivityManagerNative获取到AMS的代理,到这里就开始通过Binder进行IPC调用了。我们这里继续看AMS中startActivity的实现,AMS时SystemServer进程中的众多服务之一,关于它启动的细节请参见SystemServer.java.

1
2
3
4
5
6
7
8
9
10
11
[AMS.startActivity]===>[AMS.startActivityAsUser]
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

@Override
public final int startActivity(IApplicationThread caller, String
callingPackage,Intent intent, String resolvedType, IBinder resultTo,String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options){//启动流程在AMS的入口
return startActivityAsUser(caller, callingPackage, intent, resolvedType, resultTo,
resultWho, requestCode,
startFlags, profileFile, profileFd, options, UserHandle.getCallingUserId());
}

这里我们对传递的参数做个说明:

  • caller:代表Launcher的ApplicationThread 它是个Binder对象
  • callingPackage: 调用者即Launcher的包名
  • Intent: 要启动的activity的意图
  • resolvedType: Intent中指定的MIME类型 一般不指定的为null
  • resultTo : token 代表着Launcher的activityRecord的- appToken,实际上就是代表着Launcher.
  • resultWho : null
  • requestCode:-1
  • startFlags : 0
  • profileFile:-1
  • profileFd:null
  • Options:null
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

[AMS.startActivityAsUser]===>[ASS.startActivityAsUser]
frameworks/base/services/java/com/android/server/am/ActivityManagerService.java

@Override
public final int startActivityAsUser(IApplicationThread caller, String callingPackage,
Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags,
String profileFile, ParcelFileDescriptor profileFd, Bundle options, int userId) {
enforceNotIsolatedCaller("startActivity");
userId = handleIncomingUser(Binder.getCallingPid(), Binder.getCallingUid(), userId,false, true, "startActivity", null);
// TODO: Switch to user app stacks here.
//mStackSupervisor是一个ActivityStackSupervisor ,从名字上看是对ActivityStack进行操作的
//这里callingUid为-1 profileFile为null profileFd为null
return mStackSupervisor.startActivityMayWait(caller, -1, callingPackage, intent, resolvedType,
resultTo, resultWho, requestCode, startFlags, profileFile, profileFd,
null, null, options, userId);
}

AMS作为activity的管理者,它很懒,不做什么事情,几乎大部分Service都类似,他们不会真正的做事情,而是交给其他的"代理"对象去做事情。这里的"代理"对象就是ActivityStackSupervisor从名称上来看它负责监控和管理ActivityStack。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java

final int startActivityMayWait(IApplicationThread caller, int callingUid,
String callingPackage, Intent intent, String resolvedType, IBinder resultTo,
String resultWho, int requestCode, int startFlags, String profileFile,
ParcelFileDescriptor profileFd, WaitResult outResult, Configuration config,
Bundle options, int userId) {
……
// Collect information about the target of the Intent.
ActivityInfo aInfo = resolveActivity(intent, resolvedType, startFlags,
profileFile, profileFd, userId);//收集参数Intent的相关信息到aInfo中

synchronized (mService) {
int callingPid;//Launcher:默认传递进来的为-1
if (callingUid >= 0) {
callingPid = -1;
} else if (caller == null) {
callingPid = Binder.getCallingPid();
callingUid = Binder.getCallingUid();
} else {
callingPid = callingUid = -1;//Launcher:D
}

………
//继续调用startActivityLocked进行启动流程
int res = startActivityLocked(caller, intent, resolvedType,
aInfo, resultTo, resultWho, requestCode, callingPid, callingUid,
callingPackage, startFlags, options, componentSpecified, null);

……
}

startActivityMayWait方法中会从待启动的activity的intent中获取ActivityInfo,随后再去设置callingPid 和 callingUid为-1.在进一步调用startActivityLocked。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java

final int startActivityLocked(IApplicationThread caller,
Intent intent, String resolvedType, ActivityInfo aInfo, IBinder resultTo,
String resultWho, int requestCode,
int callingPid, int callingUid, String callingPackage, int startFlags, Bundle options,
boolean componentSpecified, ActivityRecord[] outActivity) {

ProcessRecord callerApp = null;
if (caller != null) {//校验调用者进程对于Launcher来说 即Launcher所在的应用进程
callerApp = mService.getRecordForAppLocked(caller);//查找调用者在AMS中的ProcessRecord信息
if (callerApp != null) {
callingPid = callerApp.pid;//调用者的进程id
callingUid = callerApp.info.uid;//调用者的用户id
}……
}


/做一些权限检测工作
final int startAnyPerm = mService.checkPermission(
START_ANY_ACTIVITY, callingPid, callingUid);
final int componentPerm = mService.checkComponentPermission(aInfo.permission, callingPid,
callingUid, aInfo.applicationInfo.uid, aInfo.exported);


//为新的Activity创建ActivityRecord AMS中AcitivtyRecord用来描述Activity
ActivityRecord r = new ActivityRecord(mService, callerApp, callingUid, callingPackage,
intent, resolvedType, aInfo, mService.mConfiguration,
resultRecord, resultWho, requestCode, componentSpecified, this);

//继续调用启动流程
//Launcher:sourceRecord保存着Launcher Activity的实体信息 需要注意的是这里doResume参数默认位true
err = startActivityUncheckedLocked(r, sourceRecord, startFlags, true, options);

}

这个方法主要做的事情包括:
1.初始化调用者的进程id和用户id,这是通过查找它的ProcessRecord来进行的。
2.做一些权限检查,比如调用者的权限和启动组件的权限等
3.为待启动的activity创建AtivityRecord,同时会创建appToken,用来代表这个ActivityRecord,间接代表要启动的activity.
4.进一步调用startActivityUncheckedLocked来进一步启动,这里的sourceRecord为Launcher的ActivityRecord。r就是我们要启动的activity的activityRecord

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
final int startActivityUncheckedLocked(ActivityRecord r,
ActivityRecord sourceRecord, int startFlags, boolean doResume,
Bundle options) {
……
if (((launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0 &&
(launchFlags&Intent.FLAG_ACTIVITY_MULTIPLE_TASK) == 0)
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_TASK
|| r.launchMode == ActivityInfo.LAUNCH_SINGLE_INSTANCE) {

if (r.resultTo == null) {
//Launcher:这里调用findTaskLocked找到是否存在r的实例,这里查找的结果应该是null,因为是从Launcher加载
ActivityRecord intentActivity = r.launchMode != ActivityInfo.LAUNCH_SINGLE_INSTANCE
? findTaskLocked(r)
: findActivityLocked(intent, r.info);

}
}
……

if (r.resultTo == null && !addingToTask
&& (launchFlags&Intent.FLAG_ACTIVITY_NEW_TASK) != 0) {//Launcher:true 需要一个新的task
targetStack = adjustStackFocus(r);
moveHomeStack(targetStack.isHomeStack());
if (reuseTask == null) {
r.setTask(targetStack.createTaskRecord(getNextTaskId(),
newTaskInfo != null ? newTaskInfo : r.info,
newTaskIntent != null ? newTaskIntent : intent,
true), null, true);//创建TaskRecord 并保存在r的task成员中
} else {
r.setTask(reuseTask, reuseTask, true);
}
newTask = true;
……
}
……
mService.grantUriPermissionFromIntentLocked(callingUid, r.packageName,intent, r.getUriPermissionsLocked());

targetStack.mLastPausedActivity = null;
targetStack.startActivityLocked(r, newTask, doResume, keepCurTransition, options);
mService.setFocusedActivityLocked(r);

}

这一步会首先为要启动的activity找到一个task,然而由Launcher启动的时候activity的task还并未创建,这时候需要为其创建一个task并通过setTask设置到r中去。紧接着这里调用startActivityLocked进一步处理,同时将mLastPausedActivity置null,表示当前没有被暂停的activity。将mFocusedActivity设置为当前的activity,表示为焦点activity.对于Launcher启动这里newTask为true。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
final void startActivityLocked(ActivityRecord r, boolean newTask,
boolean doResume, boolean keepCurTransition, Bundle options) {
TaskRecord rTask = r.task;//ActivityRecord中存储的TaskRecord
final int taskId = rTask.taskId;
if (taskForIdLocked(taskId) == null || newTask) {
insertTaskAtTop(rTask);
mWindowManager.moveTaskToTop(taskId);
}
……
task.addActivityToTop(r);//将ActivityRecord放到task栈的顶部
task.setFrontOfTask();//将task栈设置为前台栈

r.putInHistory();

if (!isHomeStack() || numActivities() > 0) {
……
}else{
mWindowManager.addAppToken(task.mActivities.indexOf(r), r.appToken,
r.task.taskId, mStackId, r.info.screenOrientation, r.fullscreen,
(r.info.flags & ActivityInfo.FLAG_SHOW_ON_LOCK_SCREEN) != 0, r.userId,r.info.configChanges);
}
if (doResume) {
mStackSupervisor.resumeTopActivitiesLocked();//又回到ActivityStackSupervisor
}
}

这一步首先将要启动的activity对应的ActivityRecord 即r放到其对应TaskRecord的顶部,然后将其Task设置为前台栈.随后为该Activity添加AppWindowToken,这个token时WMS用来标记AMS端的Activity对应的window的。最后调用resumeTopActivitiesLocked进一步处理栈顶activity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
boolean resumeTopActivitiesLocked() {
return resumeTopActivitiesLocked(null, null, null);
}

boolean resumeTopActivitiesLocked(ActivityStack targetStack, ActivityRecord target,
Bundle targetOptions) {
if (targetStack == null) {
targetStack = getFocusedStack();
}
boolean result = false;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (isFrontStack(stack)) {
if (stack == targetStack) {
result = stack.resumeTopActivityLocked(target, targetOptions);
} else {
stack.resumeTopActivityLocked(null);
}
}
}
return result;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
final boolean resumeTopActivityLocked(ActivityRecord prev, Bundle options) {
ActivityRecord next = topRunningActivityLocked(null);
……
mStackSupervisor.mStoppingActivities.remove(next);
mStackSupervisor.mGoingToSleepActivities.remove(next);
next.sleeping = false;
mStackSupervisor.mWaitingVisibleActivities.remove(next);
……
//暂停当前执行的activity 为栈顶activity启动坐准备
boolean pausing = mStackSupervisor.pauseBackStacks(userLeaving);
if (mResumedActivity != null) {//当前正在执行的activity
pausing = true;
startPausingLocked(userLeaving, false);//暂定activity
}

……
if (prev != null) {

}else{
if (mNoAnimActivities.contains(next)) {//如果next不包含入场动画
anim = false;
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_NONE, false);
} else {
mWindowManager.prepareAppTransition(AppTransition.TRANSIT_ACTIVITY_OPEN, false);
}
}

ActivityStack lastStack = mStackSupervisor.getLastStack();
if (next.app != null && next.app.thread != null) {
……
}else{
……
mStackSupervisor.startSpecificActivityLocked(next, true, true);
}
}

这组方法用来恢复启动task栈顶的activity,其中next即我们要执行的activity,它已经被放在了task栈顶,这里如果next已经在相关的休眠或者停止队列中需要将其从中移除,并重置sleeping状态,这些都是为next的启动做准备。这里最重要的一步就是需要将当前正在执行的mResumedActivity 暂停,这样才能执行task栈顶的activity .这是通过startSpercificActivityLocked来执行的。

1
2
3
4
5
6
7
8
9
10
11
12
13
 void startSpecificActivityLocked(ActivityRecord r,
boolean andResume, boolean checkConfig) {
// Is this activity's application already running?
ProcessRecord app = mService.getProcessRecordLocked(r.processName,
r.info.applicationInfo.uid, true);
if (app != null && app.thread != null) {
……
}

mService.startProcessLocked(r.processName, r.info.applicationInfo, true, 0,
"activity", r.intent.getComponent(), false, false, true);

}

这个方法用来启动我们具体的activity,首先获取activity对应的进程信息ProcessRecord,由于Launcher启动,activity的进程还未创建,所以这里需要为activity创建进程。

1
2
3
4
5
6
7
8
9
private final void startProcessLocked(ProcessRecord app,
String hostingType, String hostingNameStr) {
……
//为服务或者activity创建新的进程 通过zygote进程执行 创建完成后回调ActivityThread并执行其main方法
Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",
app.processName, uid, uid, gids, debugFlags, mountExternal,
app.info.targetSdkVersion, app.info.seinfo, null);
……
}

到这里会通过zygote为activity创建进程,这是通过和zygote进程通过socket通信来完成的,zygote为Activity创建进程后,会调用ActivityThread的main方法。

我们看看ActivityThread的main方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static void main(String[] args) {
……
Looper.prepareMainLooper();

ActivityThread thread = new ActivityThread();
thread.attach(false);

if (sMainThreadHandler == null) {
sMainThreadHandler = thread.getHandler();
}

AsyncTask.init();
Looper.loop();

throw new RuntimeException("Main thread loop unexpectedly exited");
}

进程启动后需要创建要给ActivityThread对象,并调用其attach方法。在attach方法中会做许多初始工作。从main方法可以看到进程的主线程是作为ui线程的。

1
2
3
4
5
6
7
8
9
10
11
12
13
private void attach(boolean system) {
sCurrentActivityThread = this;
mSystemThread = system;
if (!system) {
……
IActivityManager mgr = ActivityManagerNative.getDefault();
try {
mgr.attachApplication(mAppThread);
} catch (RemoteException ex) {
// Ignore
}
}else{……}
}

在attach方法中会调用AMS的attachApplicaton,这里的mAppThread是我们的ApplicationThread对象,它是一个binder服务,在ActivityThread对象创建的时候生成,它在这里传递给AMS,这样AMS就可以使用其代理binder来和应用程序进行通信。比如activity众多的生命周期事件是通过这个binder对象通知应用端的。

1
2
3
4
5
6
7
8
9
 @Override
public final void attachApplication(IApplicationThread thread) {
synchronized (this) {
int callingPid = Binder.getCallingPid();
final long origId = Binder.clearCallingIdentity();
attachApplicationLocked(thread, callingPid);//进一步调用
Binder.restoreCallingIdentity(origId);
}
}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
private final boolean attachApplicationLocked(IApplicationThread thread,
int pid) {

app.makeActive(thread, mProcessStats);
……
thread.bindApplication(processName, appInfo, providers,
app.instrumentationClass, profileFile, profileFd, profileAutoStop,
app.instrumentationArguments, app.instrumentationWatcher,
app.instrumentationUiAutomationConnection, testMode, enableOpenGlTrace,
isRestrictedBackupMode || !normalMode, app.persistent,
new Configuration(mConfiguration), app.compat, getCommonServicesLocked(),
mCoreSettingsObserver.getCoreSettingsLocked());
……

if (normalMode) {
try {
if (mStackSupervisor.attachApplicationLocked(app, mHeadless)) {
didSomething = true;
}
} catch (Exception e) {
badApp = true;
}
}

// Find any services that should be running in this process...
if (!badApp) {
try {
didSomething |= mServices.attachApplicationLocked(app, processName);
} catch (Exception e) {
badApp = true;
}
}

……
}

这里AMS做一些初始化工作后 又会调用到应用端的bindApplication。应用端会在这个时机为应用创建Application对象,随后AMS分别调用mStackSupervisor和mServices的attachApplicationLocked,这里会将等待启动的acitivty或者service启动起来。后面我们继续分析

1
2
3
4
5
6
7
8
9
10
11
12
13
public final void bindApplication(String processName,
ApplicationInfo appInfo, List<ProviderInfo> providers,
ComponentName instrumentationName, String profileFile,
ParcelFileDescriptor profileFd, boolean autoStopProfiler,
Bundle instrumentationArgs, IInstrumentationWatcher instrumentationWatcher,
IUiAutomationConnection instrumentationUiConnection, int debugMode,
boolean enableOpenGlTrace, boolean isRestrictedBackupMode, boolean persistent,
Configuration config, CompatibilityInfo compatInfo, Map<String, IBinder> services,
Bundle coreSettings) {

……
sendMessage(H.BIND_APPLICATION, data);
}

这里会通过H对象 其实是个handler 来发送BIND_APPLICATION消息,这会调用handleBindApplication方法来处理该消息。

1
2
3
4
5
6
7
8
private void handleBindApplication(AppBindData data) {
……
Application app = data.info.makeApplication(data.restrictedBackupMode, null);
mInitialApplication = app;
……
mInstrumentation.callApplicationOnCreate(app);
……
}

在应用端的handleBindApplication时会为应用创建application对象,同时调用onCreate回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
boolean attachApplicationLocked(ProcessRecord app, boolean headless) throws Exception {
boolean didSomething = false;
final String processName = app.processName;
for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
final ActivityStack stack = mStacks.get(stackNdx);
if (!isFrontStack(stack)) {
continue;
}
ActivityRecord hr = stack.topRunningActivityLocked(null);
if (hr != null) {
if (hr.app == null && app.uid == hr.info.applicationInfo.uid
&& processName.equals(hr.processName)) {
try {
if (headless) {

} else if (realStartActivityLocked(hr, app, true, true)) {
didSomething = true;
}
} catch (Exception e) {
Slog.w(TAG, "Exception in new application when starting activity "
+ hr.intent.getComponent().flattenToShortString(), e);
throw e;
}
}
}
}
if (!didSomething) {
ensureActivitiesVisibleLocked(null, 0);
}
return didSomething;
}

AMS回调完成应用端的application初始化后,会进一步调用attachApplicationLocked来继续执行activity的任务。在这个方法中首先取到前台的ActivityStack,然后找到task栈顶的activity,最后通过realStartActivityLocked来真正的启动hr所代表的activity.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
frameworks/base/services/java/com/android/server/am/ActivityStackSupervisor.java
final boolean realStartActivityLocked(ActivityRecord r,
ProcessRecord app, boolean andResume, boolean checkConfig)
throws RemoteException {
……
mWindowManager.setAppVisibility(r.appToken, true);
……
r.app = app;
app.waitingToKill = null;
r.launchCount++;
r.lastLaunchTime = SystemClock.uptimeMillis();
……
app.thread.scheduleLaunchActivity(new Intent(r.intent), r.appToken,
System.identityHashCode(r), r.info,
new Configuration(mService.mConfiguration), r.compat,
app.repProcState, r.icicle, results, newIntents, !andResume,
mService.isNextTransitionForward(), profileFile, profileFd,
profileAutoStop);
……
}

到这一步,WMS会将app的设置为可见,这里是将r.appToken作为key的,这个appToken是我们在为activity创建ActivityRecord时创建的,它作为一个Binder用来在WMS端标记我们的activity,同时也可以和WMS通信。随后通知应用端开始加载Activity,App.thread就是我们的ApplicationThread,它是在进程创建后,应用端的binder server,主要被AMS使用和应用端的通信。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public final void scheduleLaunchActivity(Intent intent,            IBinder token, int ident,ActivityInfo info, 
Configuration curConfig, CompatibilityInfo compatInfo,
int procState, Bundle state, List<ResultInfo> pendingResults,
List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,String profileName, ParcelFileDescriptor profileFd,
boolean autoStopProfiler) {

updateProcessState(procState, false);

ActivityClientRecord r = new ActivityClientRecord();

r.token = token;//token? 这个token实际上就是ActivityRecord的appToken 代表了待启动的Activity
r.ident = ident;
r.intent = intent;
r.activityInfo = info;
r.compatInfo = compatInfo;
r.state = state;

r.pendingResults = pendingResults;
r.pendingIntents = pendingNewIntents;

r.startsNotResumed = notResumed;
r.isForward = isForward;

r.profileFile = profileName;
r.profileFd = profileFd;
r.autoStopProfiler = autoStopProfiler;

updatePendingConfiguration(curConfig);

sendMessage(H.LAUNCH_ACTIVITY, r);
}

在scheduleLaunchActivity中构造了一个 ActivityClientRecord对象,随后发送H_LAUNCH_ACTIVITY,然后调用handleLaunchActivity。

1
2
3
4
5
6
7
8
9
10
11
12
private void handleLaunchActivity(ActivityClientRecord r, Intent customIntent) {
Activity a = performLaunchActivity(r, customIntent);
if (a != null) {
r.createdConfig = new Configuration(mConfiguration);
Bundle oldState = r.state;
//紧接着执行resume activity的流程
handleResumeActivity(r.token, false, r.isForward,
!r.activity.mFinished && !r.startsNotResumed);
……
}
……
}

到这里就开始加载activity,首先是调用performLaunchActivity,这里面会去调用onCreate和onStart等回调,而handleResumeActivity中会将activity显示出来,并调用onResume回调。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
private Activity performLaunchActivity(ActivityClientRecord r, Intent customIntent) {
……
java.lang.ClassLoader cl = r.packageInfo.getClassLoader();
//创建activi的实例
activity = mInstrumentation.newActivity(
cl, component.getClassName(), r.intent);

……
if (activity != null) {
//为activity创建context 实际上为contextImpl
Context appContext = createBaseContextForActivity(r, activity);
CharSequence title = r.activityInfo.loadLabel(appContext.getPackageManager());
Configuration config = new Configuration(mCompatConfiguration);
//调用activity的attach进行初始化

activity.attach(appContext, this, getInstrumentation(), r.token,r.ident, app, r.intent, r.activityInfo, title, r.parent,r.embeddedID, r.lastNonConfigurationInstances, config);

if (customIntent != null) {
activity.mIntent = customIntent;
}
r.lastNonConfigurationInstances = null;
activity.mStartedActivity = false;
int theme = r.activityInfo.getThemeResource();
if (theme != 0) {
activity.setTheme(theme);
}

activity.mCalled = false;
//回调onCreate
mInstrumentation.callActivityOnCreate(activity, r.state);
if (!activity.mCalled) {
throw new SuperNotCalledException(
"Activity " + r.intent.getComponent().toShortString() +
" did not call through to super.onCreate()");
}
r.activity = activity;
r.stopped = true;
if (!r.activity.mFinished) {
activity.performStart();//onStart回调
r.stopped = false;
}
……
}
r.paused = true;

mActivities.put(r.token, r);
}

这个方法主要创建activity对象,并为其创建context,实际上为contextImpl,通过attach方法将context设置到activity中。同时为activity设置window,即PhoneWindow.
随后回调onCreate,onStart等方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
final void handleResumeActivity(IBinder token, boolean clearHide, boolean isForward,
boolean reallyResume) {

ActivityClientRecord r = performResumeActivity(token, clearHide);
……
if (r.window == null && !a.mFinished && willBeVisible) {
r.window = r.activity.getWindow();
View decor = r.window.getDecorView();//取到decorView
decor.setVisibility(View.INVISIBLE);
ViewManager wm = a.getWindowManager();//取到WindowManager实际为WindowManagerImpl
WindowManager.LayoutParams l = r.window.getAttributes();
a.mDecor = decor;
l.type = WindowManager.LayoutParams.TYPE_BASE_APPLICATION;//window类型 测量Z序会用到
l.softInputMode |= forwardBit;
if (a.mVisibleFromClient) {
a.mWindowAdded = true;
wm.addView(decor, l);//这里会添加window到WMS中
}
}
……
}

到这里就真正的将activity相应的window添加到了WMS中,activity被显示在桌面上。

坚持原创技术分享,您的支持将鼓励我继续创作!